#
# Copyright 2023 CloudWeGo Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

ARCH			:= avx avx2 sse
TMP_DIR			:= output
OUT_DIR			:= internal/native
SRC_FILE		:= native/native.c

CPU_avx			:= amd64
CPU_avx2		:= amd64
CPU_sse  		:= amd64

TMPL_avx		:= native_amd64_test
TMPL_avx2		:= native_amd64_test
TMPL_sse 		:= native_amd64_test

CFLAGS_avx		:= -msse -mno-sse4 -mavx -mpclmul -mno-avx2 -mstack-alignment=0 -DUSE_AVX=1 -DUSE_AVX2=0
CFLAGS_avx2		:= -msse -mno-sse4 -mavx -mpclmul -mavx2 -mstack-alignment=0 -DUSE_AVX=1 -DUSE_AVX2=1 
CFLAGS_sse		:= -msse -mno-sse4 -mno-avx -mno-avx2 -mpclmul

CC_amd64		:= clang14
ASM2ASM_amd64	:= tools/asm2asm/asm2asm.py

CFLAGS			:= -mno-red-zone
CFLAGS			+= -target x86_64-apple-macos11
CFLAGS			+= -fno-asynchronous-unwind-tables
CFLAGS			+= -fno-builtin
CFLAGS			+= -fno-exceptions
CFLAGS			+= -fno-rtti
CFLAGS			+= -fno-stack-protector
CFLAGS			+= -nostdlib
CFLAGS			+= -O3
CFLAGS			+= -Wall

NATIVE_SRC		:= $(wildcard native/*.h)
NATIVE_SRC		+= $(wildcard native/*.c)

.PHONY: all clean ${ARCH}

define build_tmpl
	$(eval @arch := $(1))
	$(eval @tmpl := $(2))
	$(eval @dest := $(3))

${@dest}: ${@tmpl}
	mkdir -p $(dir ${@dest})
	echo '// Code generated by Makefile, DO NOT EDIT.' > ${@dest}
	echo >> ${@dest}
	sed -e 's/{{PACKAGE}}/${@arch}/g' ${@tmpl} >> ${@dest}
endef

define build_arch
	$(eval @cpu		:= $(value CPU_$(1)))
	$(eval @deps	:= $(foreach tmpl,$(value TMPL_$(1)),${OUT_DIR}/$(1)/${tmpl}.go))
	$(eval @asmin	:= ${TMP_DIR}/$(1)/native.s)
	$(eval @asmout	:= ${OUT_DIR}/$(1)/native_text_${@cpu}.go)
	$(eval @stubin	:= ${OUT_DIR}/native_${@cpu}.tmpl)
	$(eval @stubout	:= ${OUT_DIR}/$(1)/native_${@cpu}.go)

$(1): ${@asmout} ${@deps}

${@asmout}: ${@stubout} ${NATIVE_SRC}
	mkdir -p ${TMP_DIR}/$(1)
	$${CC_${@cpu}} $${CFLAGS} $${CFLAGS_$(1)} -S -o ${TMP_DIR}/$(1)/native.s ${SRC_FILE}
	python3 $${ASM2ASM_${@cpu}} -r ${@stubout} ${TMP_DIR}/$(1)/native.s

$(eval $(call 	\
	build_tmpl,	\
	$(1),		\
	${@stubin},	\
	${@stubout}	\
))

$(foreach 							\
	tmpl,							\
	$(value TMPL_$(1)),				\
	$(eval $(call 					\
		build_tmpl,					\
		$(1),						\
		${OUT_DIR}/${tmpl}.tmpl,	\
		${OUT_DIR}/$(1)/${tmpl}.go	\
	))								\
)
endef

all: ${ARCH}

clean:
	for arch in ${ARCH}; do \
		rm -vfr ${TMP_DIR}/$${arch}; \
		rm -vfr ${OUT_DIR}/$${arch}; \
	done

$(foreach 								\
	arch,								\
	${ARCH},							\
	$(eval $(call build_arch,${arch}))	\
)
